#include <buola/scene/ccamera.h>
#include <buola/scene/ctransform.h>

namespace buola { namespace scene {

CCamera::CCamera()
    :   mProjectionValid(false)
    ,   mAspect(4.0/3.0)
{
}

CCamera::~CCamera()
{

}

void CCamera::SetAspect(double pAspect)
{
    mAspect=pAspect;
    mProjectionValid=false;
}

void CCamera::LookAt(const mat::CVec3d &pAt,const mat::CVec3d &pFrom,const mat::CVec3d &pUp)
{
    mAt=pAt;
    mFrom=pFrom;
    mUp=pUp/norm(pUp);
}

void CCamera::LookAt(const mat::CVec3d &pAt,const mat::C3DRotation &pOri,double pDist)
{
    mAt=pAt;
    
    mat::CQuat_d lOri(pOri);
    
    mUp=lOri*mat::CVec3d{0,0,1};
    mFrom=mAt-pDist*(lOri*mat::CVec3d{0,1,0});
}

void CCamera::LookFrom(const mat::CVec3d &pFrom,const mat::CQuat_d &pOri)
{
    mFrom=pFrom;
    
    mat::CQuat_d lOri(pOri);
    
    mUp=lOri*mat::CVec3d{0,0,1};
    mAt=mFrom+lOri*mat::CVec3d{0,1,0};
}

mat::CMat34d CCamera::GetLookAtMatrix()
{
    if(mTransform)
    {
        const mat::CMat34d &lWorld=mTransform->GetWorldTransform();
        return mat::look_at(lWorld*mAt,lWorld*mFrom,free_vector_product(lWorld,mUp));
    }
    else
    {
        return mat::look_at(mAt,mFrom,mUp);
    }
}

void CCamera::AttachTo(PTransform pTransform)
{
    mTransform=pTransform;
}

/*namespace scene*/ } /*namespace buola*/ }
